import axios, { type AxiosRequestConfig, type InternalAxiosRequestConfig } from "axios";
import { ElMessage } from "element-plus";
import { useUserStore } from "@/stores/user";

/**
 * @description 定义请求成功的接口模型
 * @export
 * @interface IResponseType
 * @template T  data类型, 无法指定时可传入any
 */
export interface IResponseType<T = any> {
    code: number;
    data: T;
    message: string;
    time: number;
}

export interface IRequestOptions<D = any> extends AxiosRequestConfig<D> {
    /**
     * 发送请求时是否在headers里带上token等用户信息
     */
    token?: boolean;
    /**
     * 是否在code不为1000时自动显示错误提示
     */
    error?: "message" | "none";
}

export interface CommonListResponse<T> {
    data: T[];
    totalCount: number;
}

const defaultOptions: IRequestOptions = {
    baseURL: import.meta.env.VITE_BASE_API,
    method: "get",
    error: "none",
    token: true,
    headers: {
        "Content-Type": "application/json",
        platform: "aip",
        environment: "1",
        source: "99",
    },
};

const service = axios.create(defaultOptions);
service.interceptors.request.use(
    (config: InternalAxiosRequestConfig & { token?: boolean }) => {
        if (config.token !== false) {
            const { token, userId, memberId } = useUserStore();
            token && (config.headers.token = token);
            userId && (config.headers.userId = userId);
            memberId && (config.headers.memberId = memberId);
        }
        return config;
    },
    (err) => {
        return Promise.reject(err);
    },
);
service.interceptors.response.use(
    ({ data, config, status }) => {
        if (status !== 200) return Promise.reject({ status, config, data });
        
        if (data.code === 1101) {
            const userStore = useUserStore();
            userStore.logout();
        }
        if (data.code !== 1000 && (config as IRequestOptions).error === "message") {
            ElMessage.error(data.message);
        }
        return data;
    },
    (error) => {
        return Promise.reject(error.response);
    },
);

const request = async <T = any>(url: string, options?: IRequestOptions): Promise<IResponseType<T>> => {
    return service({ ...options, url });
};
request.get = request;
request.delete = async <T = any>(url: string, options?: IRequestOptions): Promise<IResponseType<T>> => {
    return request(url, { ...options, method: "delete" });
};
request.post = async <T = any>(
    url: string,
    data?: Record<string, any>,
    options?: IRequestOptions,
): Promise<IResponseType<T>> => {
    return request(url, { ...options, method: "post", data });
};
request.put = async <T = any>(
    url: string,
    data?: Record<string, any>,
    options?: IRequestOptions,
): Promise<IResponseType<T>> => {
    return request(url, { ...options, method: "put", data });
};
export default request;
